#!/usr/bin/env python

import pygame
from pygame.locals import *


def line_draw( x0, y0, x1, y1, color, antialias, surf ):
    def trivial( x0, y0, x1, y1, color, surf ):
        """Uses floating point operations to calculate values"""

        dx = x1 - x0
        if dx < 0:
            dx = -dx
            y1, y0 = y0, y1
            x1, x0 = x0, x1

        dy = y1 - y0

        # Speed up special cases
        if dx == 0: # vertical, need to have in separate, since dy/dx = \inf
            if dy < 0:
                y0, y1 = y1, y0
            for y in xrange( y0, y1 ):
                surf.set_at( ( x0, y ), color )
        elif dy == 0: # horizontal
            for x in xrange( x0, x1 ):
                surf.set_at( ( x, y0 ), color )
        else:
            if dx > abs( dy ):
                m = float( dy ) / float( dx )

                y = y0
                for x in xrange( x0, x1 ):
                    surf.set_at( ( x, int( y ) ), color )

                    y += m
            else:
                m = float( dx ) / float( dy )
                if dy < 0:
                    dy = -dy
                    y0, y1 = y1, y0
                    x0, x1 = x1, x0

                x = x0
                for y in xrange( y0, y1 ):
                    surf.set_at( ( int( x ), y ), color )
                    x += m
    # trivial()


    def bresenham( x0, y0, x1, y1, color, surf ):
        """Uses integer only operations to calculate values"""
        dx = x1 - x0
        dy = y1 - y0
        if dx < 0:
            dx = -dx
            step_x = -1
        else:
            step_x = 1

        if dy < 0:
            dy = -dy
            step_y = -1
        else:
            step_y = 1

        x = x0
        y = y0
        if dx > dy:
            e = - ( dx / 2 )
            while x != x1:
                surf.set_at( ( x, y ), color )
                x += step_x
                e += dy
                if e >= 0:
                    y += step_y
                    e -= dx


        else:
            e = - ( dy / 2 )
            while y != y1:
                surf.set_at( ( x, y ), color )
                y += step_y
                e += dx
                if e >= 0:
                    x += step_x
                    e -= dy

    # bresenham()

    ## Base (correct) line
    #pygame.draw.line( surf, Color( "gray50" ), ( x0, y0 ), ( x1, y1 ), 5 )
    #trivial( x0, y0, x1, y1, color, surf )
    bresenham( x0, y0, x1, y1, color, surf )
# line_draw()


pygame.init()

screen = pygame.display.set_mode( ( 800, 600 ) )
screen.fill( Color( "black" ) )

line_draw( 800, 150, 0,   150, Color( "yellow" ), 0, screen )
line_draw( 0,   450, 800, 450, Color( "yellow" ), 0, screen )

line_draw( 300,   0, 300, 600, Color( "yellow" ), 0, screen )
line_draw( 600, 600, 600, 0,   Color( "yellow" ), 0, screen )

line_draw( 0, 0, 800,  10, Color( "blue" ), 0, screen )
line_draw( 0, 0, 800, 600, Color( "blue" ), 0, screen )
line_draw( 0, 0, 400, 600, Color( "blue" ), 0, screen )
line_draw( 0, 0, 800, 300, Color( "blue" ), 0, screen )
line_draw( 0, 0, 10,  600, Color( "blue" ), 0, screen )

line_draw( 800, 0, 0, 600, Color( "green" ), 0, screen )
line_draw( 400, 0, 0, 600, Color( "green" ), 0, screen )
line_draw( 800, 0, 0, 300, Color( "green" ), 0, screen )

line_draw( 0, 0, 800, 10, Color( "magenta" ), 0, screen )
line_draw( 0, 0, 10, 600, Color( "magenta" ), 0, screen )
line_draw( 0, 590, 800, 600, Color( "magenta" ), 0, screen )
line_draw( 790, 0, 800, 600, Color( "magenta" ), 0, screen )

line_draw( 0, 10, 800, 0, Color( "cyan" ), 0, screen )
line_draw( 10, 0, 0, 600, Color( "cyan" ), 0, screen )
line_draw( 0, 600, 800, 590, Color( "cyan" ), 0, screen )
line_draw( 800, 0, 790, 600, Color( "cyan" ), 0, screen )


run = True
clock = pygame.time.Clock()
while run:
    for e in pygame.event.get():
        if e.type == QUIT or \
               e.type == KEYDOWN and e.key == K_ESCAPE:
            run = False
    pygame.display.flip()
    clock.tick( 24 )
